import datetime
import logging
import os
import random
import re
from time import sleep
from selenium.webdriver.support import expected_conditions as EC
import allure
import pytest
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.select import Select
# from common.ver.verify import Verify
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.wait import WebDriverWait

from common.Logger import logger
from common.decs import relations
from common.set_url import read_file_method1


class Web:

    def __init__(self):
        # 当前运行的浏览器的类型
        self.br = 'gc'
        # 运行自动化的驱动对象
        self.driver: webdriver.Chrome
        self.relations = {}

    def openbrowser(self, browser='gc'):
        """
        打开浏览器
        :param browser:
        :return:
        """
        if browser == 'gc' or browser == '':
            self.br = 'gc'
            # #获取上一级文件夹路径，读取driver路径
            # dir_path = os.path.dirname(os.getcwd())
            # 获取根目录路径
            root_dir = os.path.abspath(os.sep)
            self.driver = webdriver.Chrome(root_dir + "Myframe/common/driver/chromedriver.exe")
        elif browser == 'ff':
            self.br = 'ff'
            self.driver = webdriver.Firefox()
        elif browser == 'ie':
            self.br = 'ie'
            self.driver = webdriver.Ie()
        else:
            self.br = 'gc'
            print("浏览器类型不支持，默认使用谷歌")
            self.driver = webdriver.Chrome()

        self.driver.maximize_window()
        self.driver.implicitly_wait(10)
        return self.driver

    @relations
    def __find_ele(self, locator: str = ''):
        """
        统一定为方式
        :param locator: 元素定位器，同时能够支持id和xpath以及css
        :return:定位到的元素，如果没有就返回None
        """
        self.driver.implicitly_wait(20)
        if locator is None or locator == '':
            return None
        elif locator.startswith('/'):
            ele = self.driver.find_element(By.XPATH, locator)
            try:
                wait = WebDriverWait(self.driver, 10).until(
                    EC.presence_of_element_located((By.XPATH, locator))
                )
            except Exception as e:
                logger.info("等待超时页面无法查询到该元素：", locator)
            return ele
        elif locator.startswith('#') or locator.__contains__('>'):
            ele = self.driver.find_element(By.CSS_SELECTOR, locator)
            try:
                wait = WebDriverWait(self.driver, 10).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, locator))
                )
            except Exception as e:
                logger.info("等待超时页面无法查询到该元素：", locator)
            return ele
        else:
            # 默认用id定位

            ele = self.driver.find_element(By.ID, locator)
            try:
                wait = WebDriverWait(self.driver, 10).until(
                    EC.presence_of_element_located((By.ID, locator))
                )
            except Exception as e:
                logger.info("等待超时页面无法查询到该元素：", locator)

            return ele

    # @relations
    # def Swipe(self, locator=""):
    #
    #         # 判断使用什么定位方式
    #         ele = self.__find_ele(locator)
    #         # 滑动滚动条到某个指定的元素
    #         # js4 = "arguments[0].scrollIntoView()"
    #         xpath = "//div[contains(text(), '生产工艺')]"
    #         result =f"""document.evaluate({0}}, document, null, XPathResult.ANY_TYPE, null)""".format(xpath)
    #         r=self.driver.execute_script(result)
    #         e=self.driver.execute_script(r.iterateNext())
    #
    #         js_code="""document.querySelector('[data-key="craft"]').scrollIntoView({})"""
    #         self.driver.execute_script(js4)
    #         sleep(0.5)

    def Swipe(self, locator=""):
        # 判断使用什么定位方式
        ele = self.__find_ele(locator)
        text = ele.text
        logging.info(text)
        if locator.startswith("//div"):
            xpathlocator = f"//div[contains(text(), '{text}')]"
        elif locator.startswith("//span"):
            xpathlocator = f"//span[contains(text(), '{text}')]"
        else:
            xpathlocator = f"//*[contains(text(), '{text}')]"
        # xpath = "//div[contains(text(), '生产工艺')]"
        logging.info(xpathlocator)
        # 使用 JavaScript 执行 XPath 查询
        js_code = f"""
        const xpath = "{xpathlocator}";
        const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
        const node = result.singleNodeValue;
        if (node) {{
            node.scrollIntoView();
        }}
        """

        # 执行 JavaScript 代码
        self.driver.execute_script(js_code)

        # 等待一段时间以确保滚动完成
        sleep(0.5)

    @relations
    def click(self, locator, start=""):
        """
        点击元素
        :param locator: 元素定位器
        :return:
        """
        sleep(0.3)
        i = 0
        while i <= 5:
            if start is None or start == "":
                ele = self.__find_ele(locator)
                ele.click()
                break
            elif start:
                locator = f"//{start}[text()='{locator}']"
                # ele="//%s[contains(text(),'%s')]"%(start,locator)
                ele = self.__find_ele(locator)
                logger.info(ele)
                ele.click()
                break
            else:
                sleep(0.5)
                i += 1
        sleep(0.2)

    @relations
    def double_click(self, locator=""):
        ele = self.__find_ele(locator)
        # 对定位到的元素执行鼠标双击操作
        ActionChains(self.driver).double_click(ele).perform()

    @relations
    def td_input(self, locator="", value=""):

        ele = self.__find_ele(locator)
        # 对定位到的元素执行鼠标双击操作
        ActionChains(self.driver).double_click(ele).perform()
        sleep(0.5)
        # 双击后出现input标签
        input_ele = self.__find_ele(locator + "/child::input")
        self.sleep(0.5)
        # 对定位到的元素执行鼠标双击操作
        ActionChains(self.driver).double_click(input_ele).perform()
        # 全选输入框的内容
        input_ele.send_keys(Keys.CONTROL, "a")
        input_ele.send_keys(value)

    @relations
    def clicks(self, locator, num):
        '''

        :param locator: 定位参数
        :param num: 数字
        :return:
        '''
        i = 0
        while i < 5:
            try:
                ele = self.__find_ele(locator)
                ele[num].click()
                sleep(0.2)
                break
            except Exception as e:
                i += 1
                sleep(1)
                continue

    @relations
    def input(self, locator, value):
        """
        文本输入
        :param locator: 元素定位器
        :param value: 需要输入的文本内容
        :return:
        """
        i = 0
        while i < 5:
            try:
                ele = self.__find_ele(locator)
                # 全选输入框的内容
                ele.send_keys(Keys.CONTROL, "a")
                ele.send_keys(value)
                logger.info("输入：" + value)
                break
            except Exception as e:
                i += 1
                sleep(1)
                continue
    def __seturl(self):
        '''
        设置环境
        :param url:
        :return:
        '''
        url=read_file_method1()
        # # 设置测试环境
        # test = "http://scm-test1.yizheyun.cn"
        # pre = "https://scm-pre.yizheyun.com"
        # pro = "https://scm.yizheyun.com"
        self.url = url
        return self.url

    def geturl(self, path=""):
        '''o
        打开网站
        :param path:需要打开的网站的路径
        :return:
        '''
        self.refresh()
        url = self.__seturl()
        if path.__contains__("http"):
            self.driver.get(path)
        elif path.startswith("/"):
            path = url + path
            self.driver.get(path)
        else:
            url = self.__seturl()
            path = url + "/" + path
            self.driver.get(path)
        self.sleep(1)
        self.driver.implicitly_wait(20)

    @relations
    def inputs(self, locator, num, value):
        '''
        :param locator: 定位参数
        :param num: 数字
        :return:
        '''
        ele = self.__find_ele(locator)
        ele[num].send_keys(value)
        sleep(0.2)

    @relations
    def clickjs(self, locator):
        """
        通过js点击
        :param locator:
        :return:
        """
        ele = self.__find_ele(locator)
        self.driver.execute_script("arguments[0].click()", ele)
        sleep(0.2)

    def intoiframe(self, locator):
        """
        进入iframe
        :param locator:
        :return:
        """
        ele = self.__find_ele(locator)
        self.driver.switch_to.frame(ele)

    def outiframe(self):
        """
        :return:
        """
        self.driver.switch_to.default_content()

    def select(self, locator, value):
        """
        下拉框选择
        :param locator:
        :param value: 选择的值
        :return:
        """
        ele = self.__find_ele(locator)
        select = Select(ele)
        try:
            int(value)
            select.select_by_value(value)
        except:
            select.select_by_visible_text(value)

    @relations
    def moveto(self, locator):
        """
        鼠标悬停
        :param locator:``
        :return:
        """
        ele = self.__find_ele(locator)
        action = ActionChains(self.driver)
        # perform()表示让action生效
        action.move_to_element(ele).perform()
        sleep(1)

    @relations
    def gettext(self, locator, reg):
        """
        获取文本并且保存为全局变量
        :param locator:
        :param reg:获取文本的正则表达式
        :return:
        """
        ele = self.__find_ele(locator)
        text = ele.text
        print(text)
        if reg:
            text = re.findall(reg, text)[0]
        self.relations['text'] = text
        print(text)
        print(self.relations)

    def refresh(self):
        self.driver.refresh()

    # def __get_relations(self, params: str = ''):
    #     """
    #     获取关联
    #     :param params: 需要关联的参数
    #     :return: 返回关联后的字符串
    #     """
    #     if params:
    #         for key in self.relations:
    #             params = params.replace('{' + key + '}', str(self.relations.get(key)))
    #     # print(params)
    #     return params

    def saveparam(self, paramname="", value=""):
        """
        增加一个参数
        :param paramname: 参数名
        :param value: 参数值
        :return:
        """
        if paramname.startswith("//"):
            ele = self.__find_ele(paramname)
            text = ele.text
            self.relations[value] = text
        else:
            self.relations[paramname] = value

    def switchwin(self):
        """切换窗口"""
        handles = self.driver.window_handles
        logger.info(handles)
        # self.driver.close()
        self.driver.switch_to.window(handles[-1])
        sleep(1)

    def backwin(self):
        sleep(1)
        handles = self.driver.window_handles
        logger.info(handles)
        # self.driver.close()
        self.driver.switch_to.window(handles[-1])

    def getwin(self):
        sleep(1)
        handles = self.driver.window_handles
        logger.info(handles)
        self.driver.switch_to.window(handles[0])

    def sleep(self, num):
        sleep(int(num))

    def quit(self):
        sleep(3)
        self.driver.quit()
        # self.driver.close()

    @relations
    def assertequal(self, loctaor="", value=""):
        logging.info("预期文案：" + value)
        try:
            i = 1
            text = "null"
            # 获取文案
            while i <= 3:
                try:
                    # 判断使用什么定位方式
                    self.moveto(loctaor)
                    ele = self.__find_ele(loctaor)
                    text = ele.text
                    logging.info("断言文案：" + text)
                    break
                except Exception as e:
                    logging.info("无法获取到元素：" + loctaor)
                    self.driver.refresh()
                    logging.info("页面刷新" + str(i) + "次")
                    sleep(0.5)
                    i += 1
            if text.__contains__(value) or value.__contains__(text):
                logger.info("断言通过")
            else:
                sleep(1)
                logging.info("断言文案：" + text)
                allure.attach(self.driver.get_screenshot_as_png(), "错误截图", allure.attachment_type.PNG)
                pytest.fail()
        except Exception as e:
            allure.attach(self.driver.get_screenshot_as_png(), "错误截图", allure.attachment_type.PNG)
            pytest.fail()

    def assertdelete(self, locator=""):
        sleep(1)
        try:
            ele = self.__find_ele(locator)
            text = ele.text
        except Exception as e:
            text = "pass"
        if text == "pass":
            pass
        else:
            pytest.fail("断言失败")

    def randon_upload(self, locator=""):
        root_dir = os.path.abspath(os.sep)
        path = "Myframe/lib/testfile"
        img_list = os.listdir(root_dir + path)
        i = random.randint(0, 31)
        img = img_list[i]
        srcfile = root_dir + path + "/" + img
        ele = self.__find_ele(locator)
        logger.info(srcfile)
        ele.send_keys(srcfile)
        sleep(1)

    def upload(self, locator="", srcfile=""):
        """
        上传文件
        """
        if srcfile.startswith("/"):
            # 获取当前文件路径的父级路径
            path = os.path.abspath('.')
            srcfile = path + srcfile
        ele = self.__find_ele(locator)
        logger.info(srcfile)
        ele.send_keys(srcfile)
        sleep(1)

    def assertattribute(self, locator="", name="", value=""):
        ele = self.__find_ele(locator)
        # 根据name名去获取对应属性值
        attribute = ele.get_attribute(name)
        logger.info("断言属性值：" + attribute)
        logger.info("预期属性值：" + value)
        if value == attribute:
            logger.info("断言通过")
        else:
            logger.info("断言失败")
            pytest.fail("断言失败")

    def get_time(self, params=""):
        # 获取当前的时间
        now = datetime.datetime.now()
        if params.__contains__("%"):
            time = now.strftime(params)
        elif params:
            # 利用反射，调用传入的方法，获取时间
            time = getattr(now, params)
        elif len(params) < 1:
            time = now.strftime("%Y%m%d%H%M%S")
        self.relations["time"] = time
        return

    def get_kh(self):
        # 获取当前时间的天数
        day = datetime.datetime.now().day
        # 获取当前时间小时数
        hour = datetime.datetime.now().hour
        # 获取当前时间分钟数
        minute = datetime.datetime.now().minute
        # 获取当前时间秒数
        second = datetime.datetime.now().second
        l1 = [day, hour, minute, second]
        l2 = []
        for i in l1:
            if i < 10:
                i = "0" + str(i)
            else:
                i = str(i)
            l2.append(i)
        kh = "".join(l2)
        self.relations["kh"] = "YZ" + kh
        logger.info("款号：" + self.relations["kh"])
        return

    def assertelement(self, locator="", keyword="", value=""):
        try:
            ele = self.__find_ele(locator)
            logger.info("识别到此元素：" + locator)
            if keyword == "click":
                ele.click()
            elif keyword == "input":
                ele.send_keys(Keys.CONTROL, "a")
                ele.send_keys(value)
                logger.info("输入：" + value)
            else:
                logger.info("无法识别操作")
        except Exception as e:
            logger.info("不存在[ " + locator + " ]元素")
            pass


if __name__ == '__main__':
    web = Web()
    web.openbrowser()
    web.geturl("user/login")
    web.assertelement("//input[@id='mobile']", "input", "19912341245")
    web.assertelement("//input[@id='password']", "input", "341245")
    web.click('//span[text()="登 录"]')
    web.sleep(2)
    web.geturl('sample-management')
    web.sleep(2)
    # web.sleep(1)
    # web.input('//input[@placeholder="员工姓名"]',"自动化员工")
    # web.click('//span[text()="查 询"]')
    # web.click('//a[text()="编辑"]')
    # web.click('//span[@aria-label="close" and @class="anticon anticon-close"]')
    # web.input('//span[text()="请选择职位"]/..//input',"newopen-设计师")
    # web.click('//div[@title="newopen-设计师"]')
    # web.click('//div[text()="编辑员工"]')
    # web.click('//span[text()="确 定"]')
    web.click('//span[text()="编 辑"]')
    web.sleep(1)
    web.switchwin()
    web.sleep(2)
    web.Swipe("//div[contains(text(), '成衣尺寸')]")
    web.click('//div[text()="成衣尺寸"]/../../../../div/..//span[text()="选择模板 >"]')
    web.click('//span[text()="自动化测试"]')
    web.sleep(3)
    web.refresh()
    web.sleep(3)
    web.quit()
    #
    # web.click('//span[@class="ant-pro-menu-item-title ant-design-pro-layout-z6d1z6" and text()="样版管理"]')
    # web.get_day()
    # web.click('//input[@id="created_at"]')
    # web.double_click('//div[contains(text(),"{day}")]')
    # web.get_type('//button[@type="button"]',"type")
    # web.click('//span[text()="新建样版"]')
    # web.click('//label[text()="设计师"]/../..//input')
    # web.click('//div[text()="总经理"]')
    # web.click('//div[text()="马可"]')
    # web.click('//label[text()="车版师"]/../..//input')
    # web.click('/html/body/div[4]/div/div/div/div/ul[1]/li[1]/div[1]')
    # web.click('/html/body/div[4]/div/div/div/div/ul[2]/li')
    # web.click('//label[text()="纸样师"]/../..//input')
    # web.click('/html/body/div[5]/div/div/div/div/ul/li[1]/div[1]')
    # web.click('/html/body/div[5]/div/div/div/div/ul[2]/li/div')
    # # i=datetime.datetime.now()
    # print("当前的日期是  %s" % i.day)
    # print("当前的月数是  %s" % i.month)
    # print("当前的年数是  %s" % i.year)
    # print("当前的年数是  %s" % i.hour)
    # print("当前的年数是  %s" % i.minute)
    # print("当前的年数是  %s" % i.second)
    # day=datetime.datetime.now().day
    # #获取当前时间小时数
    # hour = datetime.datetime.now().hour
    # #获取当前时间分钟数
    # minute = datetime.datetime.now().minute
    # #获取当前时间秒数
    # second = datetime.datetime.now().second
    # l1=[day,hour,minute,second]
    # l2=[]
    # for i in l1:
    #     if i<10:
    #         i="0"+str(i)
    #     else:
    #         i=str(i)
    #     l2.append(i)
    # print(l2)
    # print("".join(l2))
    # web.Swipe('//div[text()="其他文件"]')
    # # web.click('//div[@class="ant-upload-drag-container"]')
    #
    # web.upload('//span/input[@id="files_list"]','/lib/testfile/img1.png')
    # web.double_click('//td[text()="衣长"]/../td[3]')
    # web.sleep(2)
    # web.input('//td[text()="衣长"]/../td[3]/child::input')
    # logger.info("123")
    # web.gettext('//span[contains(text(),"款号")]','款号：(.+)')
    # sleep(3)
    # web.quit()
    # s="款号：yz001"
    # s1=re.findall("款号：(.+)",s)
    # print(os.path.abspath('.'))
